﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using MyMoviesBrowserLibrary.MyMovies;
using System.IO;
using System.Net;
using System.ComponentModel;
using System.Runtime.Remoting.Messaging;
using System.Windows.Threading;
using MyMoviesBrowserLibrary;


namespace TVManager
{
    /// <summary>
    /// Interaction logic for MoviesFanartControl.xaml
    /// </summary>
    public partial class MoviesFanartControl : UserControl
    {
        private MyMoviesDataContext ctx;
        private Title selectedTitle;
        private Dictionary<string, string> queue;

        public MoviesFanartControl()
        {
            InitializeComponent();
            ctx = MyMoviesBusiness.GetNewMyMoviesDataContext();
            queue = new Dictionary<string, string>();

            downloadPosterButton.Click += new RoutedEventHandler(downloadPosterButton_Click);
            selectPosterButton.Click += new RoutedEventHandler(selectPosterButton_Click);
            downloadBackgroundButton.Click += new RoutedEventHandler(downloadBackgroundButton_Click);
            selectBackgroundButton.Click += new RoutedEventHandler(selectBackgroundButton_Click);
            downloadButton.Click += new RoutedEventHandler(downloadButton_Click);

            movieListBox.SelectionChanged += new SelectionChangedEventHandler(movieListBox_SelectionChanged);
            Loaded += new RoutedEventHandler(MoviesFanartContrcol_Loaded);
        }

        void downloadButton_Click(object sender, RoutedEventArgs e)
        {
            DownloadImagesAsync();
        }

        void UpdateStatus(string updateText)
        {
            this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)delegate()
            {
                statusControl.StatusText = updateText;
            });
        }

        private delegate void DownloadImagesDelegate();
        void DownloadImages()
        {
            MyMoviesBusiness bl = new MyMoviesBusiness();
            List<Title> titles = movieListBox.ItemsSource.Cast<Title>().ToList();
            statusControl.Show();
            queue.Clear();
            bool downloadFolder, downloadFanart;
            foreach (Title title in titles)
            {
                UpdateStatus(string.Format("Checking images for '{0}'", title.OriginalTitle));
                downloadFolder = !File.Exists(System.IO.Path.Combine(title.MovieDirectory, "folder.jpg"));
                downloadFanart = !File.Exists(System.IO.Path.Combine(title.MovieDirectory, "fanart.jpg"));

                if (downloadFolder || downloadFanart)
                {
                    UpdateStatus(string.Format("Fetching image data for '{0}'", title.OriginalTitle));
                    Movie movie = bl.GetDefualtImages(title.OriginalTitle, title.nvcIMDB);
                    if (movie != null)
                    {
                        if (downloadFolder && !string.IsNullOrEmpty(movie.PosterUrl))
                            queue.Add(System.IO.Path.Combine(title.MovieDirectory, "folder.jpg"), movie.PosterUrl);
                        if (downloadFanart && !string.IsNullOrEmpty(movie.BackgroundUrl))
                            queue.Add(System.IO.Path.Combine(title.MovieDirectory, "fanart.jpg"), movie.BackgroundUrl);
                    }
                }
            }
            DownloadQueue();
        }
        public void DownloadImagesAsync()
        {
            DownloadImagesDelegate worker = new DownloadImagesDelegate(DownloadImages);
            AsyncCallback completedCallback = new AsyncCallback(DownloadImagesCallback);

            AsyncOperation async = AsyncOperationManager.CreateOperation(null);
            worker.BeginInvoke(completedCallback, async);
        }
        private void DownloadImagesCallback(IAsyncResult ar)
        {
            // get the original worker delegate and the AsyncOperation instance
            DownloadImagesDelegate worker =
              (DownloadImagesDelegate)((AsyncResult)ar).AsyncDelegate;
            AsyncOperation async = (AsyncOperation)ar.AsyncState;

            // finish the asynchronous operation
            worker.EndInvoke(ar);
        }

        void DownloadQueue()
        {
            if (queue.Count == 0)
            {
                statusControl.Hide();
                return;
            }

            string key = queue.Keys.First();
            string value = queue[key];
            queue.Remove(key);

            statusControl.Show();
            UpdateStatus(string.Format("Downloading image ({0} left)", queue.Count));

            WebClient client = new WebClient();
            client.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(client_DownloadFileCompleted);
            client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
            statusControl.IsIndeterminate = false;

            client.DownloadFileAsync(new Uri(value), key);
        }

        void selectBackgroundButton_Click(object sender, RoutedEventArgs e)
        {
            BrowseForImage("fanart");
            LoadImage(backgroundImage, "fanart");
        }

        void downloadBackgroundButton_Click(object sender, RoutedEventArgs e)
        {
            if (selectedTitle == null)
                return;
            ChooseMovieImageWindow window = new ChooseMovieImageWindow(selectedTitle.OriginalTitle, selectedTitle.nvcIMDB, "fanart");
            window.ImageSelected += new ImageSelectedEvent(window_ImageSelected);
            window.ShowDialog();
        }

        void window_ImageSelected(object sender, string imageUrl, string imageType)
        {
            if (selectedTitle == null)
                return;

            statusControl.StatusText = "Downloading Image";
            statusControl.Show();
            if (imageType == "fanart")
                backgroundImage.Source = null;
            else if (imageType == "folder")
                posterImage.Source = null;

            string imageLocation = System.IO.Path.Combine(selectedTitle.MovieDirectory, imageType + ".jpg");

            WebClient client = new WebClient();
            client.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(client_DownloadFileCompleted);
            client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);            
            statusControl.IsIndeterminate = false;

            client.DownloadFileAsync(new Uri(imageUrl), imageLocation, imageType);
        }

        void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            statusControl.ProgressBarValue = e.ProgressPercentage;
        }

        void client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show("There was an error downloading image.");
            }
            else if(e.UserState != null)
            {
                string imageType = e.UserState.ToString();
                if (imageType == "fanart")
                    LoadImage(backgroundImage, "fanart");
                else if (imageType == "folder")
                    LoadImage(posterImage, "folder");
            }

            statusControl.Hide();
            DownloadQueue();
        }

        void selectPosterButton_Click(object sender, RoutedEventArgs e)
        {
            BrowseForImage("folder");
            LoadImage(posterImage, "folder");
        }

        void downloadPosterButton_Click(object sender, RoutedEventArgs e)
        {
            if (selectedTitle == null)
                return;
            ChooseMovieImageWindow window = new ChooseMovieImageWindow(selectedTitle.OriginalTitle, selectedTitle.nvcIMDB, "folder");
            window.ImageSelected += new ImageSelectedEvent(window_ImageSelected);
            window.ShowDialog();
        }

        private void BrowseForImage(string imageType)
        {
            if (selectedTitle == null)
                return;
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            dlg.Filter = "Images|*.jpg;*.png;";

            // Show open file dialog box
            bool? result = dlg.ShowDialog();
            string fileName;
            // Process open file dialog box results
            if (result == true)
            {
                // Open document
                fileName = dlg.FileName;
            }
            else
                return;

            FileInfo fi = new FileInfo(fileName);
            if (fi.Exists)
                fi.CopyTo(System.IO.Path.Combine(selectedTitle.MovieDirectory, imageType + ".jpg"));
        }

        void movieListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            selectedTitle = movieListBox.SelectedValue as Title;
            if (selectedTitle == null)
            {
                movieGrid.Visibility = Visibility.Collapsed;
                return;
            }
            movieGrid.Visibility = Visibility.Visible;

            LoadImage(posterImage, "folder");
            LoadImage(backgroundImage, "fanart");
        }

        void MoviesFanartContrcol_Loaded(object sender, RoutedEventArgs e)
        {
            var movies = ctx.Titles.OrderBy(t => t.SortTitle).ToList();
            movieListBox.ItemsSource = movies;
        }

        void LoadImage(Image image, string imageType)
        {
            string imageFile = System.IO.Path.Combine(selectedTitle.MovieDirectory, imageType + ".jpg");
            if (File.Exists(imageFile))
            {
                BitmapImage bitmap = new BitmapImage();
                bitmap.BeginInit();
                bitmap.StreamSource = new MemoryStream(File.ReadAllBytes(imageFile));
                bitmap.EndInit();
                image.Source = bitmap;
            }
            else
                image.Source = null;
        }

    }
}
